import { randomBytes } from 'crypto';
import { getHash, encrypt, decrypt } from './util.js';
import { BLOCKS_PATH } from './constants.js';
import fs from 'fs-extra';

const { writeFileSync, removeSync, existsSync } = fs;

/**
 * 区块
 */
export class Block {
  /**
   * 上个节点的hash
   * @type {String}
   */
  prevHash = null;

  /**
   * 随机字节
   * @type {Buffer}
   */
  randomByte = null;

  /**
   * @type {Buffer}
   */
  data = null;

  /**
   * 构造函数
   * @param data{Buffer} 数据
   * @param prevHash{string} 上个节点的Hash
   */
  constructor(data, prevHash = '0'.repeat(64), randomByte = randomBytes(64)) {
    this.prevHash = prevHash;
    if (!(data instanceof Buffer)) {
      data = Buffer.from(data);
    }
    this.data = data;
    this.randomByte = randomByte;
  }

  /**
   * 加密后的节点数据
   */
  get encryptedContent() {
    return encrypt(
      Buffer.concat([
        Buffer.from(this.prevHash),
        Buffer.from(this.randomByte),
        Buffer.from(this.data),
      ])
    );
  }

  /**
   * 节点hash
   */
  get hash() {
    return getHash(this.encryptedContent);
  }

  /**
   * 节点存放在硬盘上的位置
   */
  get filePath() {
    return `${BLOCKS_PATH}/${this.hash}`;
  }

  /**
   * 写入区块到硬盘
   */
  write() {
    return writeFileSync(this.filePath, this.encryptedContent);
  }

  /**
   * 删除硬盘上的区块信息
   */
  delete() {
    return existsSync(this.filePath) && removeSync(this.filePath);
  }

  /**
   * 解密函数
   * @param buffer{Buffer} 解密前buffer
   */
  static decrypt(buffer) {
    const raw = decrypt(buffer);
    const prevHash = raw.slice(0, 64).toString();
    const randomByte = raw.slice(64, 128);
    const data = raw.slice(128);
    return new Block(data, prevHash, randomByte);
  }
}

export default Block;
